using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using ApplicationLibrary.DataGridViewControls;
using ApplicationLibrary.DBManager;
using ApplicationLibrary.SqlConnector;

namespace ApplicationLibrary.ExtendedControls
{
    public abstract partial class RadarForm : Form
    {
        private DataSet rdrDataSet = null;
        private SqlABConnection rdrConnection = null;
        private SqlABDataAdapter rdrDataAdapter = null;
        private string code = string.Empty;

        protected SqlABCommand rdrFindSqlCommand = null;
        protected SqlABCommand rdrBrowseSqlCommand = null;

        protected string strBrowseQuery = string.Empty;
        protected string strFindQuery = string.Empty;
        protected string rdrCodeColumn = string.Empty;
        protected string rdrDescColumn = string.Empty;
        protected string rdrNameSpace = string.Empty;
        protected IRadarParameters rdrParameters = null;
        protected Table rdrTable = null;

        abstract protected string DefineBrowseQuery(SqlABCommand sqlCmd, string findQuery);

        abstract protected bool DefineFindQuery(SqlABCommand sqlCmd);

        abstract protected Table GetRadarTable();

        abstract protected void PrepareFindQuery(IRadarParameters param);

        abstract protected IRadarParameters PrepareRadarParameters(DataGridViewRow row);

        abstract public IRadarParameters GetRadarParameters(string text);

        abstract public string GetCodeFromParameters(IRadarParameters param);

        virtual protected void PrepareBrowseQuery() { }

        virtual protected void OnFound(SqlABDataReader sqlReader)
        {
            if (RadarFormFoundRecord != null)
                RadarFormFoundRecord(this, sqlReader);
        }

        /// <summary>
        /// The value contained in description column
        /// </summary>
        ///
        public string FindQuery { get; set; }

        public string FilterType { get; set; }

        public string Description { get; protected set; }

        public string Seed { set { code = value; } get { return code; } }

        public bool EnableAddOnFly { get; set; }

        public bool MustExistCode { get; set; }

        public System.Resources.ResourceManager ResourceManager { get; set; }

        public delegate void RadarFormRowSelectedEventHandler(object sender, RadarFormRowSelectedArgs pe);

        public event RadarFormRowSelectedEventHandler RadarFormRowSelected;

        public delegate void RadarFormFoundRecordEventHandler(object sender, SqlABDataReader sqlReader);

        public event RadarFormFoundRecordEventHandler RadarFormFoundRecord;

        [Obsolete("Too param")]
        public RadarForm(SqlABConnection myconn)
            : base()
        {
            rdrConnection = myconn;
        }

        public RadarForm()
        {
            this.Left = GlobalInfo.MainForm.Left + 50;
            this.Top = GlobalInfo.MainForm.Top + 50;
            this.StartPosition = FormStartPosition.Manual;
            rdrConnection = GlobalInfo.DBaseInfo.dbManager.DB_Connection;
            MustExistCode = true;
            InitializeComponent();
            dataGridView1.AutoGenerateColumns = false;
        }

        protected override void OnLoad(EventArgs e)
        {
            InitializeConnection();
            AddColumnToGrid();
            if (GlobalInfo.globalPref.ExpandSearchWindow)
                WindowState = FormWindowState.Maximized;

            base.OnLoad(e);
        }

        public bool CanOpenNew
        {
            get { return rdrNameSpace != string.Empty; }
        }

        public void OpenNew(IRadarParameters param)
        {
            Debug.Assert(rdrNameSpace != string.Empty, "Missing namespace");
            this.code = GetCodeFromParameters(param);
            if (rdrNameSpace != string.Empty)
            {
                DocumentForm frm = (DocumentForm)GlobalInfo.CreateForm(rdrNameSpace);
                frm.PostLoaded += new DocumentForm.PostFormLoadEventHandler(frm_PostLoaded);
                frm.ShowDialog();
                Requery();
            }
        }

        private void frm_PostLoaded(object sender, ApplicationLibrary.DBManager.DBManager dbManager)
        {
            DocumentForm frm = (DocumentForm)sender;
            frm.ToolbarEvent(DocumentForm.ToolbarEventKind.New);
            Debug.Assert(frm.KeyControl != null, "Missing KeyControl");
            frm.KeyControl.Text = code;
        }

        public bool Find(IRadarParameters param)
        {
            bool found = false;
            InitializeConnection();

            PrepareFindQuery(param);

            SqlABDataReader reader = rdrFindSqlCommand.ExecuteReader();

            if (reader.Read())
            {
                OnFound(reader);
                found = true;
            }
            reader.Close();
            return found;
        }

        public bool ValidateValue(IRadarParameters code, out string error)
        {
            error = string.Empty;
            if (code != null && !Find(code))
            {
                if (EnableAddOnFly && CanOpenNew)
                {
                    DialogResult result = MessageBox.Show(Properties.Resources.Rdr_CodeNotFound,
                    Properties.Resources.Warning,
                    MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (result == DialogResult.Yes)
                        OpenNew(code);
                }
                else if (MustExistCode)
                {
                    error = string.Format(Properties.Resources.Rdr_NotFound, code);
                    MessageBox.Show(error,
                    Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                return false;
            }
            else
            {
                if (code == null)
                {
                    Description = string.Empty;
                    return true;
                }
            }

            return true;
        }

        private void InitializeConnection()
        {
            if (rdrDataSet != null) return;

            rdrTable = GetRadarTable();
            CreateConnection();
            DefineFindQuery(rdrFindSqlCommand);
        }

        private void CreateConnection()
        {
            rdrDataSet = new DataSet("GridDataSet");
            rdrFindSqlCommand = new SqlABCommand(rdrConnection.providerType);
            rdrFindSqlCommand.Connection = rdrConnection;

            rdrBrowseSqlCommand = new SqlABCommand(rdrConnection.providerType);
            rdrBrowseSqlCommand.Connection = rdrConnection;

            rdrBrowseSqlCommand.CommandText = DefineBrowseQuery(rdrBrowseSqlCommand, string.Empty);
            rdrDataAdapter = new SqlABDataAdapter(rdrBrowseSqlCommand);
        }

        protected override void OnShown(EventArgs e)
        {
            PrepareBrowseQuery();
            //if (!code.Equals(string.Empty))
            //{
            cbxField1.SelectedIndex = 0;
            cbxCompareType1.SelectedIndex = 1;
            //txtValue1.Text = code;
            cbxAndOr.SelectedIndex = -1;
            Requery();
            //}
            rdrDataSet.Clear();
            rdrDataAdapter.Fill(rdrDataSet, "Radar");

            dataGridView1.DataSource = rdrDataSet;
            dataGridView1.DataMember = "Radar";
        }

        private void AddColumnToGrid()
        {
            if (dataGridView1.Columns.Count != 0) return;

            for (int t = 0; t < rdrTable.VisibleInRadarCount; t++)
            {
                iColumn col = rdrTable[t];
                cbxField1.Items.Add(col.Description);
                cbxField2.Items.Add(col.Description);

                TrimMaskedTextBoxDataGridViewColumn txtColumn = new TrimMaskedTextBoxDataGridViewColumn();
                txtColumn.Name = col.Name;
                txtColumn.HeaderText = col.Description;
                txtColumn.DataPropertyName = col.Name;
                txtColumn.EnumsType = col.EnumType;
                txtColumn.SortMode = DataGridViewColumnSortMode.Automatic;
                txtColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
                if (col.EnumType != typeof(System.DBNull))
                {
                    dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
                    txtColumn.ResourceManager = ResourceManager;
                }
                if (col.Description == string.Empty)
                    txtColumn.Visible = false;
                txtColumn.ReadOnly = true;
                dataGridView1.Columns.Add(txtColumn);
            }
        }

        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
        }

        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex != -1)
            {
                SelectRow(e.RowIndex);
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex != -1 && tsbPin.Checked)
                SelectRow(e.RowIndex);
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (dataGridView1.CurrentRow != null)
            {
                SelectRow(dataGridView1.CurrentRow.Index);
                this.DialogResult = DialogResult.OK;
            }
            else
                this.DialogResult = DialogResult.Cancel;

            this.Close();
        }

        private void SelectRow(int rowIndex)
        {
            if (rdrDescColumn != string.Empty)
                Description = dataGridView1.Rows[rowIndex].Cells[rdrDescColumn].Value.ToString();

            if (rdrCodeColumn != string.Empty)
                Seed = dataGridView1.Rows[rowIndex].Cells[rdrCodeColumn].Value.ToString();

            if (RadarFormRowSelected != null && rowIndex >= 0)
            {
                RadarFormRowSelected(this, new RadarFormRowSelectedArgs(PrepareRadarParameters(dataGridView1[rowIndex])));
            }
        }

        private void tsbExpand_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                splGrid.SplitterDistance += (tsbExpand.Checked) ? -50 : 50;
            }
            else
            {
                int sd = splGrid.SplitterDistance;
                int ne = this.Height + ((tsbExpand.Checked) ? 50 : -50);
                this.Size = new Size(this.Width, this.Height + ((tsbExpand.Checked) ? 50 : -50));
                splGrid.SplitterDistance = sd;
                if (ne != this.Height) splGrid.SplitterDistance -= ne - this.Height;
            }
        }

        private void tsbSearch_Click(object sender, EventArgs e)
        {
            Requery();
        }

        private void ResetQuery()
        {
            if (cbxField2.Text == string.Empty)
            {
                cbxField1.SelectedIndex = -1;
                cbxCompareType1.SelectedIndex = -1;
                txtValue1.Text = string.Empty;
                cbxAndOr.SelectedIndex = -1;
            }
            else
            {
                cbxField2.SelectedIndex = -1;
                cbxCompareType2.SelectedIndex = -1;
                txtValue2.Text = string.Empty;
                cbxAndOr.SelectedIndex = -1;
            }
            Requery();
        }

        private void Requery()
        {
            SqlABCommand requery = new SqlABCommand(GlobalInfo.LoginInfo.ProviderType);
            requery.Connection = rdrConnection;

            string strSelect = string.IsNullOrEmpty(FindQuery) ? string.Empty : FindQuery;
            if (cbxField1.Text.Length > 0 && cbxCompareType1.Text.Length > 0)
            {
                strSelect += (strSelect.Length > 0 ? " AND " : string.Empty) +
                            CreateQuery(cbxField1.SelectedIndex, cbxCompareType1.SelectedIndex, txtValue1.Text);

                if (cbxAndOr.Text.Length > 0 && cbxField2.Text.Length > 0 && cbxCompareType2.Text.Length > 0)
                {
                    strSelect += string.Format(" {0} ", cbxAndOr.Text);
                    strSelect += CreateQuery(cbxField2.SelectedIndex, cbxCompareType2.SelectedIndex, txtValue2.Text);
                }
            }
            strSelect = DefineBrowseQuery(requery, strSelect);
            PrepareBrowseQuery();

            rdrDataSet.Clear();
            rdrDataAdapter.SelectCommand = requery;
            requery.CommandText = strSelect;
            rdrDataAdapter.Fill(rdrDataSet, "Radar");
        }

        private string CreateQuery(int index, int mode, string val)
        {
            string[] operation = { "LIKE", "LIKE", "=", "!=", "<", "<=", ">", ">=" };
            //			CONTAINS
            //			START WITH
            //			EQUAL
            //			NOT EQUAL
            //			LESS
            //			LESS OR EQUAL
            //			GREATHER
            //			GREATHER OR EQUAL

            string result = string.Format("{0} {1} '{2}'", rdrTable[index].Name, operation[mode],
                (mode == 0 ? "%" : "") + val.Trim() + (mode < 2 ? "%" : ""));

            return result;
        }

        private void tsbCancel_Click(object sender, EventArgs e)
        {
            ResetQuery();
        }

        private void dataGridView1_KeyUp(object sender, KeyEventArgs e)
        {
        }

        private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (dataGridView1.CurrentRow != null)
                {
                    SelectRow(dataGridView1.CurrentRow.Index);
                    this.DialogResult = DialogResult.OK;
                }
                else
                    this.DialogResult = DialogResult.Cancel;

                this.Close();
            }
        }
    }

    public class RadarFormRowSelectedArgs : EventArgs
    {
        public IRadarParameters parameters;

        public RadarFormRowSelectedArgs(IRadarParameters parameters)
        {
            this.parameters = parameters;
        }
    }

    public interface IRadarParameters
    {
        object this[int index] { get; }

        List<object> Params { get; set; }

        string GetLockKey();

        T GetValue<T>(int index);
    }

    public class RadarParameters : IRadarParameters
    {
        public object this[int index]
        {
            get { return Params[index]; }
        }

        public List<object> Params { get; set; }

        public string GetLockKey()
        {
            string key = string.Empty;
            for (int t = 0; t < Params.Count; t++)
                key += Params[t].ToString() + "\t";

            return key;
        }

        public T GetValue<T>(int index)
        {
            return (T)Convert.ChangeType(Params[index], typeof(T));
        }
    }
}